package ru.picman.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.Pair;

/**
 * This class is a library for all images. You can load images (bitmaps) in it
 * and
 * get them by using the id from <i>R</i>. Note that this class does not provide
 * the
 * required functionality to store two images of a different size with the same
 * id.
 * If you load an image with an already existing id it simply overrides the
 * current
 * image loaded, if it exists.<br />
 * <br />
 * <b>Note:</b> Your view should typically call
 * <code>ImageLibrary.setResources(getResources());</code> before using the
 * functions in this class.
 * 
 * @author Matthijs
 */
public final class ImageLibrary
{
	/**
	 * Private constructor so this class can not be instantiated.
	 */
	private ImageLibrary() {}
	
	/**
	 * Load an image.
	 * 
	 * @param id The R-id of the image
	 * @param w The desired image width
	 * @param h The desired image height
	 * @return A pair with the drawable and the raw image
	 */
	public static Pair<Drawable,Bitmap> load(int id, int w, int h) {
		if (resources == null)
			throw new NullPointerException("Resources is null. Use setResources(Resources)");
		
		Drawable drawable = resources.getDrawable(id);
		add(drawable,null,id);
		return resize(id,w,h);
	}
	
	/**
	 * Adds a set of a drawable and a raw image bitmap to the library, with
	 * the specified id.
	 * 
	 * @param d The drawable
	 * @param b The bitmap
	 * @param id The id for the image
	 */
	public static void add(Drawable d, Bitmap b, int id) {
		imageList.add(new Pair<Drawable,Bitmap>(d,b));
		imagesIdToIndex.put(new Integer(id),new Integer(imageList.size() - 1));
	}
	
	/**
	 * Checks if an image with the specified id exists.
	 * 
	 * @param id The id
	 * @return If an image exists, true, false otherwise
	 */
	public static boolean exists(int id) {
		return imagesIdToIndex.containsKey(new Integer(id));
	}
	
	/**
	 * Returns the id of every image in the library.
	 * 
	 * @return Every id in an array list
	 */
	public static Set<Integer> getAll() {
		return imagesIdToIndex.keySet();
	}
	
	/**
	 * Returns the drawable of the image with id <i>id</i>.
	 * 
	 * @param id The id
	 * @return The drawable, or null if the id does not exist
	 */
	public static Drawable getDrawable(int id) {
		Integer idx = imagesIdToIndex.get(new Integer(id));
		return (idx != null ? imageList.get(idx.intValue()).first : null);
	}
	
	/**
	 * Returns the bitmap of the image with id <i>id</i>.
	 * 
	 * @param id The id
	 * @return The bitmap, or null if the id does not exist
	 */
	public static Bitmap getBitmap(int id) {
		Integer idx = imagesIdToIndex.get(new Integer(id));
		return (idx != null ? imageList.get(idx.intValue()).second : null);
	}
	
	/**
	 * Resizes the image with the specified id to an image with width w
	 * and height h. The result set is returned. An exception is thrown
	 * if the id does not exist in the library.
	 * 
	 * @param id The id of the image
	 * @param w The desired image width
	 * @param h The desired image height
	 * @return The drawable, bitmap pair
	 * @throws NullPointerException if the id does not exists
	 */
	public static Pair<Drawable,Bitmap> resize(int id, int w, int h) {
		Drawable drawable = getDrawable(id);
		if (drawable == null)
			throw new NullPointerException("id does not exist");
		
		Bitmap bitmap = Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
		Canvas canvas = new Canvas(bitmap);
		drawable.setBounds(0,0,w,h);
		drawable.draw(canvas);
		add(drawable,bitmap,id);
		return imageList.get(imageList.size() - 1);
	}
	
	/**
	 * Sets the resources class for this library. This is necessary if you
	 * want to load an image with and id from R.java.<br />
	 * The resources can be retrieved using View.getResources()
	 * 
	 * @param r The resources to set.
	 */
	public static void setResources(Resources r) {
		resources = r;
	}
	
	//
	
	private static Resources                         resources;
	
	private static final List<Pair<Drawable,Bitmap>> imageList;
	private static final Map<Integer,Integer>        imagesIdToIndex;
	
	static {
		imageList = new ArrayList<Pair<Drawable,Bitmap>>();
		imagesIdToIndex = new HashMap<Integer,Integer>();
	}
}
